﻿module Sustainalytics.Portfolio {

    import Common = Sustainalytics.Common;
    import Pager = Sustainalytics.Pager;
    import LRTM = Sustainalytics.LRTM;

    // Portfolio List controller
    export class PortfolioOverviewController {

        // portfolio filter
        public portfolioCompanyFilter: PortfolioCompanyFilterDto;
        // order by
        public orderByCol: string;
        public orderByAsc: boolean;

        // list of portfolios
        public portfolioCompanyList: Sustainalytics.Portfolio.PortfolioDetailsDto[];
        public initialPortfolioDetailsWeightList: number[];
        // current portfolio
        public portfolio: PortfolioDto;

        // total number of portfolios
        public portfolioCompanyCount: number;
        private accountId: string;
        private userId: string;
        private scopeDestroyed: boolean;
        public isMyPortfolio: boolean;
        public isRenamingPortfolioName: boolean;
        public newNamePortfolio: string;
        public portfolioExcel: any;
        public isChangingSecurityWeight: boolean;
        public isEditButtonVisible: boolean;

        private $routeParams: any;

        // Ctor.
        constructor(
            private $rootScope: ng.IScope,
            private $scope: ng.IScope,
            private $q: ng.IQService,
            private $location: ng.ILocationService,
            private RoutingService: Routing.IRoutingService,
            private PortfolioService: PortfolioService,
            private PortfolioCompanyService: PortfolioCompanyService,
            private notificationFactory: Common.INotificationFactory,
            private staticObjects: Common.IStaticObjects,
            private LongRunningTaskManagerService: LRTM.LongRunningTaskManagerService,
            private $modal: Common.IModal) {

            var ctx = this;
            ctx.$routeParams = ctx.RoutingService.getRouteParams();

            $scope['portfolioOverview'] = ctx;

            ctx.scopeDestroyed = false;

            ctx.portfolioCompanyFilter = new PortfolioCompanyFilterDto();
            ctx.portfolioCompanyFilter.portfolioId = ctx.$routeParams['id'];

            ctx.orderByCol = "CompanyNameLowercase";
            ctx.orderByAsc = true;

            if (ctx.$rootScope['userInfo'] == null) {
                ctx.$rootScope['userInfo'] = angular.fromJson(localStorage.getItem('sust_userInfo'));
            }
            ctx.accountId = ctx.$rootScope['userInfo'].accountId;
            ctx.userId = ctx.$rootScope['userInfo'].userId;

            ctx.handlePagerChanged();
            ctx.handleScopeDestroyed();

            ctx.getPortfolioById();
            ctx.isChangingSecurityWeight = false;
            ctx.initialPortfolioDetailsWeightList = new Array;
            
        }

        // when scope is destroyed keep a flag to prevent some operations
        // eg: bootstrap UI tab delete each tab and select the next that causing 
        // in current case to trigger multiple requests while tabs are being disposed 
        // which is unnecessary
        private handleScopeDestroyed() {
            var ctx = this;

            // when scope is destroyed
            ctx.$scope.$on('$destroy', function () {
                ctx.scopeDestroyed = true;
            });
        }

        // search for portfolios when pager changes
        private handlePagerChanged() {
            var ctx = this;

            ctx.$scope.$on('pagerChanged', function (ev, pager: Pager.PagerController) {
                ctx.searchPortfolioCompany();
            });
        }

        // order list of portfolios
        public setOrderByCol(col: string) {
            var ctx = this;

            if (ctx.orderByCol === col) {
                ctx.orderByAsc = !ctx.orderByAsc;
            }
            else {
                ctx.orderByCol = col;
                ctx.orderByAsc = true;
            }
            ctx.searchPortfolioCompany();
        }

        // search list of portfolios
        public searchPortfolioCompany(): ng.IPromise<{}> {
            var ctx = this;

            ctx.$rootScope['loading'] = true;

            var pager: Pager.PagerController = ctx.$scope['pager'];
            if (!pager) {
                var def = ctx.$q.defer();
                def.reject();
                return def.promise;
            }

            var skip = pager.skipCount();
            var take = pager.takeCount();

            // get portfolio items
            var promiseGet: ng.IPromise<Sustainalytics.Portfolio.PortfolioResultstDto> = ctx.PortfolioCompanyService.getPortfolioCompanies(ctx.portfolioCompanyFilter, skip, take, [ctx.orderByCol], ctx.orderByAsc, ctx.userId);

            var portfolioCompanyListTemp: Sustainalytics.Portfolio.PortfolioDetailsDto[];
            var portfolioCompanyCountTemp: number;
            //on success list portfolios
            promiseGet.then(function (lst) {
                portfolioCompanyListTemp = lst["portfolioDetails"];
                portfolioCompanyCountTemp = lst["portfolioCompanyCount"];
            });

            // after get and count are resolved set controller properties
            var promiseAll = ctx.$q.all([promiseGet]);

            promiseAll
                .then(function () {
                    ctx.portfolioCompanyList = portfolioCompanyListTemp;
                    ctx.portfolioCompanyCount = portfolioCompanyCountTemp;
                    pager.setTotalItemsCount(portfolioCompanyCountTemp);
                })
                ['finally'](function () {
                    ctx.$rootScope['loading'] = false;
                });

            return promiseAll;
        }

        public getPortfolioById(): ng.IPromise<PortfolioDto> {
            var ctx = this;

            ctx.$rootScope['loading'] = true;

            // get news by id
            var promiseGet: ng.IPromise<PortfolioDto> = ctx.PortfolioService.getPortfolioById(ctx.$routeParams['id'], ctx.accountId, ctx.userId);

            //on success
            promiseGet
                .then(function (data) {
                    ctx.portfolio = data;
                    ctx.isRenamingPortfolioName = false;
                    ctx.newNamePortfolio = data["name"];
                    ctx.isEditButtonVisible = !ctx.isChangingSecurityWeight && !ctx.portfolio.isSystemPortfolio && (ctx.portfolio.isMyPortfolio || ctx.portfolio.sharingStatus != PortfolioSharingStatus.Shared);
                })
                ['finally'](function () {
                    ctx.$rootScope['loading'] = false;
                });
            return promiseGet;
        }

        public deletePortfolioCompany(id): ng.IPromise<{}> {
            var ctx = this;

            if (confirm("Are you sure you want to remove the selected security from current portfolio?")) {

                var promiseDelete = ctx.PortfolioCompanyService.deletePortfolioCompany(id, ctx.$routeParams['id']);

                promiseDelete.then(function () {
                    // repopulate list
                    ctx.searchPortfolioCompany();
                    ctx.portfolio.dateModified = new Date();
                    ctx.portfolio.companyCount--;
                });
                return promiseDelete;
            }
            return undefined;
        }

        public setShared(item: PortfolioDto) {
            var ctx = this;

            var portfolioSharing = new PortfolioSharingDto();
            portfolioSharing.id = item.id;
            portfolioSharing.sharingStatus = PortfolioSharingStatus.Shared;

            var modalInstanceSubscribe = ctx.$modal.open({
                templateUrl: 'Views/Portfolio/portfolioExists_dialog.tpl.html',
                controller: 'PortfolioCheckController',
                size: 'lg',
                backdrop: 'static',
                resolve: {
                    message: function () {
                        return "Are you sure you want to share the portfolio?";
                    },
                    informationMessage: function () {
                    }
                }
            });

            modalInstanceSubscribe.result.then((out) => {
                if (out['portfolioCheck'] == true) {
                    var promiseUpdate = ctx.PortfolioService.updateStatusPortfolio(portfolioSharing);

                    promiseUpdate["finally"](function () {
                        item.sharingStatus = PortfolioSharingStatus.Shared;
                    });
                }
            });
        }

        public setPrivate(item: PortfolioDto) {
            var ctx = this;

            var portfolioSharing = new PortfolioSharingDto();
            portfolioSharing.id = item.id;
            portfolioSharing.sharingStatus = PortfolioSharingStatus.Private;

            var modalInstanceSubscribe = ctx.$modal.open({
                templateUrl: 'Views/Portfolio/portfolioExists_dialog.tpl.html',
                controller: 'PortfolioCheckController',
                size: 'lg',
                backdrop: 'static',
                resolve: {
                    message: function () {
                        return "Are you sure you want to unshare the portfolio?";
                    },
                    informationMessage: function () {
                        if (item.hasSubscription)
                            return "A user of the account has activated the alert service for this portfolio!"
                        else return "";
                    }
                }
            });

            modalInstanceSubscribe.result.then((out) => {
                if (out['portfolioCheck'] === true) {
                    var promiseUpdate = ctx.PortfolioService.updateStatusPortfolio(portfolioSharing);

                    promiseUpdate['finally'](function() {
                        item.sharingStatus = PortfolioSharingStatus.Private;
                    });
                }
            });
        }

        public editWeight() {
            var ctx = this;
            ctx.isChangingSecurityWeight = true;
            ctx.initialPortfolioDetailsWeightList = new Array;
            var i;
            for (i = 0; i < ctx.portfolioCompanyList.length; i++) {
                ctx.initialPortfolioDetailsWeightList.push(ctx.portfolioCompanyList[i].securityWeight);
            }
            ctx.isEditButtonVisible = false;
        }

        public isNumeric(n) {
            return !isNaN(parseFloat(n)) && isFinite(n);
        }

        // show error message for a given error code
        private showError(err) {
            var ctx = this;
            if (err && err['errorCode'])
                ctx.notificationFactory.error('', ctx.staticObjects.getErrorMesageByStatusCode(err['errorCode'], err['errorCode']));
        }

        public saveWeightChanges() {
            var ctx = this;
            ctx.isChangingSecurityWeight = false;
            var i;
            var index = 0;
            var isError = false;
            for (i = 0; i < ctx.portfolioCompanyList.length && !isError; i++) {
                if (ctx.portfolioCompanyList[i].securityWeight != ctx.initialPortfolioDetailsWeightList[i])
                {
                    if (ctx.portfolioCompanyList[i].securityWeight.toString() == "") {
                        var promiseChangeValue = ctx.PortfolioService.updatePortfolioDetailWeight(ctx.portfolio.id, ctx.portfolioCompanyList[i].id, null, true);
                        promiseChangeValue.then(() => { index++; })
                            .catch(err => {
                                ctx.portfolioCompanyList[index].securityWeight = ctx.initialPortfolioDetailsWeightList[index];
                                this.notificationFactory.error("Error", "The new value of security weight for company with Security ID:" + ctx.portfolioCompanyList[index].displayInfo.securityIdentifier + " could not be saved.");
                                isError = true;
                                index++;
                            });
                    }
                    else
                    {
                        if (!this.isNumeric(ctx.portfolioCompanyList[i].securityWeight)) {
                            this.notificationFactory.error("Error", "The new value of security weight for company with Security ID:" + ctx.portfolioCompanyList[i].displayInfo.securityIdentifier + " is not a valid number.");
                            ctx.portfolioCompanyList[i].securityWeight = ctx.initialPortfolioDetailsWeightList[i];
                        }
                        else {
                            var promiseChangeValue = ctx.PortfolioService.updatePortfolioDetailWeight(ctx.portfolio.id, ctx.portfolioCompanyList[i].id, ctx.portfolioCompanyList[i].securityWeight, false);
                            promiseChangeValue.then(() => { index++; })
                                .catch(err => {
                                    ctx.portfolioCompanyList[index].securityWeight = ctx.initialPortfolioDetailsWeightList[index];
                                    this.notificationFactory.error("Error", "The new value of security weight for company with Security ID:" + ctx.portfolioCompanyList[index].displayInfo.securityIdentifier + " could not be saved.");
                                    isError = true;
                                    index++;
                                });
                        }
                    }
                }
            }
            ctx.isEditButtonVisible = !ctx.isChangingSecurityWeight && !ctx.portfolio.isSystemPortfolio && (ctx.portfolio.isMyPortfolio || ctx.portfolio.sharingStatus != PortfolioSharingStatus.Shared);
        }

        public cancelWeightChanges() {
            var ctx = this;
            ctx.isChangingSecurityWeight = false;
            var i;
            for (i = 0; i < ctx.portfolioCompanyList.length; i++) {
                ctx.portfolioCompanyList[i].securityWeight = ctx.initialPortfolioDetailsWeightList[i];
            }
            ctx.isEditButtonVisible = !ctx.isChangingSecurityWeight && !ctx.portfolio.isSystemPortfolio && (ctx.portfolio.isMyPortfolio || ctx.portfolio.sharingStatus != PortfolioSharingStatus.Shared);
        }

        public changeIsRenaming() {
            var ctx = this;
            if (ctx.portfolio.isMyPortfolio) {
                ctx.isRenamingPortfolioName = !ctx.isRenamingPortfolioName;
                ctx.newNamePortfolio = ctx.portfolio.name;
            }
        }

        public renamePortfolio() {
            var ctx = this;

            var portfolioRename = new PortfolioRenameDto();
            portfolioRename.id = ctx.portfolio.id;
            portfolioRename.newPortfolioName = ctx.newNamePortfolio;
            portfolioRename.oldPortfolioName = ctx.portfolio.name;

            var promiseRename = ctx.PortfolioService.renamePortfolio(portfolioRename);

            promiseRename
                .then(() => {
                    this.portfolio.name = this.newNamePortfolio;
                    this.portfolio.dateModified = new Date();
                    this.isRenamingPortfolioName = false;
                })
                .catch(() => {
                });
        }

        public openAddPortfolioPopup(): void {
            var ctx = this;
            var modalInstance = ctx.$modal.open(
            {
                templateUrl: "/Views/Portfolio/addEditSystemPortfolio.tpl.html",
                controller: "SystemPortfolioController",
                size: "lg",
                backdrop: 'static',
                resolve: {
                    portfolio() {
                        return ctx.portfolio;
                    }
                }
                });

            modalInstance.result.then(doc=> {
                if (doc["portfolioStatus"]) {
                    ctx.searchPortfolioCompany();
                    ctx.getPortfolioById();
                }
            });
           
         
        }

        public addTaskExportPortfolio(): void {
            var ctx = this;
      

            var data = {
                id: ctx.$routeParams['id'], 
                accountId : ctx.accountId, 
                userId: ctx.userId,
                name: ctx.portfolio.name
            }

            ctx.LongRunningTaskManagerService.runTask(
                'Portfolio_' + ctx.portfolio.name + "_" + moment().format("DDMMYYYY"),
                angular.toJson(data),
                LRTM.LongRunningTaskTypeEnum.PortfolioExportExcel,
                true,
                null);
        }
    }


    // register controller with Portfolio Angular module
    angular.module(portfolioModuleName).controller('PortfolioOverviewController',
        ['$rootScope', '$scope', '$q', '$location', 'RoutingService', 'PortfolioService', 'PortfolioCompanyService', 'notificationFactory',
            'staticObjects', 'LongRunningTaskManagerService','$modal', PortfolioOverviewController]);
} 